using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GameAOT;
using System.Collections.Generic;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class UIQuestTrack : UIEntityWindow
    {
        #region Template Generate,don't modify

        protected class UIB_UIQuestTrack
        {
            #region ObjectBinding Generate

            public ExText textName { protected set; get; }
            public ExText textTargetDesc { protected set; get; }
            public GameObject entityMark { protected set; get; }
            public ExButton btnJump { protected set; get; }
            public ExText textMapDesc { protected set; get; }
            public GameObject descRoot { protected set; get; }

            public virtual void InitBinding(ObjectBinding __binding)
            {
                __binding.TryGetVariableValue<ExText>("textName", out var __tbv0);
                textName = __tbv0;
                __binding.TryGetVariableValue<ExText>("textTargetDesc", out var __tbv1);
                textTargetDesc = __tbv1;
                __binding.TryGetVariableValue<GameObject>("entityMark", out var __tbv2);
                entityMark = __tbv2;
                __binding.TryGetVariableValue<ExButton>("btnJump", out var __tbv3);
                btnJump = __tbv3;
                __binding.TryGetVariableValue<ExText>("textMapDesc", out var __tbv4);
                textMapDesc = __tbv4;
                __binding.TryGetVariableValue<GameObject>("descRoot", out var __tbv5);
                descRoot = __tbv5;
            }

            #endregion ObjectBinding Generate
        }

        #endregion Template Generate,don't modify


        #region Window Config

        /// <summary>
        /// 静态配置
        /// </summary>
        private static UICreateConfig _createConfig = new()
        {
            prefabName = nameof(UIQuestTrack),
            layer = EUILayer.Main,
        };

        /// <summary>
        /// 创建UI的配置
        /// </summary>
        public override IUICreateConfig createConfig => _createConfig;

        #endregion Window Config

        #region fields

        private static System.Func<bool> needRecover = () => GameDataCenter.PlayerData.quest.trackQuestCid > 0;
        private UIItemPool<UIN_QuestTargetSceneMark> _targetSceneMarkPool;
        private Dictionary<int, UIN_QuestTargetSceneMark> _activeMarks = new();
        private List<int> _expiredMark = new();

        #endregion fields

        #region properties

        protected UIB_UIQuestTrack ui { get; set; }
        protected UIMsgDispatcher uiMsgDispatcher => _msgDispatcher as UIMsgDispatcher;

        #endregion properties

        protected override void BeforeInit()
        {
            ui = new UIB_UIQuestTrack();
            ui.InitBinding(csObjBind);
        }

        protected override void OnInit()
        {
            RegisterNeedRecoverFunc(needRecover); //用字段避免GC

            _targetSceneMarkPool = InitPool<UIN_QuestTargetSceneMark>(ui.entityMark);
            isUpdate = true;
        }

        protected override void OnShow(UIBaseData data)
        {
            if (data is not UD_QuestTrack dataQuest || dataQuest.questCid == 0)
            {
                ui.descRoot.SetActive(false);
                return;
            }

            ui.descRoot.SetActive(true);
            var cfgQuest = TableCenter.quest.Get(dataQuest.questCid);
            ui.textName.text = cfgQuest.Name;

            if (string.IsNullOrEmpty(cfgQuest.Description))
            {
                ui.textTargetDesc.transform.parent.gameObject.SetActive(false);
            }
            else
            {
                ui.textTargetDesc.transform.parent.gameObject.SetActive(true);
                ui.textTargetDesc.text = cfgQuest.Description;
            }

            if (cfgQuest.TargetRegion == 0 || cfgQuest.TargetRegion ==
                (LevelPlayModule.Instance?.levelPlay?.regionCtrl?.cfgRegionPack?.cfgRegionInstance?.Id ?? 0))
            {
                ui.btnJump.SetActive(false);
            }
            else
            {
                ui.btnJump.SetActive(true);
                ui.btnJump.AddClickEvent(OnBtnJumpClick);
                ui.textMapDesc.text = TableCenter.regionInstance.Get(cfgQuest.TargetRegion)?.Name ?? string.Empty;
            }
        }

        protected override void OnHide()
        {

        }

        private void OnBtnJumpClick()
        {
            UILevelMap.TryGoto(GameDataCenter.PlayerData.quest.trackQuestCid).Forget();
        }

        /// <summary>
        /// 添加UGUI侦听
        /// </summary>
        protected override void AddUGUIListener()
        {
        }

        protected override void OnUpdate(float dt, float unscaledDt)
        {
            if (_activeMarks.Count == 0)
            {
                return;
            }

            _expiredMark.Clear();
            foreach (var kv in _activeMarks)
            {
                var entityId = kv.Key;
                var mark = kv.Value;
                var entity = GameplayAreaManager.Instance.curSceneArea.GetEntityById(entityId);
                if (entity != null)
                {
                    mark.Update();
                }
                else
                {
                    _expiredMark.Add(entityId);
                }
            }
            foreach (var id in _expiredMark)
            {
                RemoveMark(id);
            }
        }

        public UIN_QuestTargetSceneMark AddMark(TViewEntity entity)
        {
            if (_activeMarks.ContainsKey(entity.id))
            {
                LogGame.LogError("任务目标已存在");
                return null;
            }

            var item = _targetSceneMarkPool.GetOne();
            item.SetData(entity);
            item.transform.SetParent(transform, false);
            _activeMarks.Add(entity.id, item);
            return item;
        }

        private void RemoveMark(int entityId)
        {
            if (_activeMarks.Remove(entityId, out var item))
            {
                _targetSceneMarkPool.HideOne(item);
            }
        }

        private void Clear()
        {
            foreach (var kv in _activeMarks)
            {
                _targetSceneMarkPool.HideOne(kv.Value);
            }
            _targetSceneMarkPool.Clear();
            _activeMarks.Clear();
        }

        protected override void OnDispose()
        {
            Clear();
        }
    }
}